﻿using NHibernate;
using NHibernate.Criterion;
using System.Linq;

namespace NMA.Infrastructure.NHibernate.Repository
{
    using NMA.Infrastructure.NHibernate.Paging;
    using System.Linq.Expressions;
    using System;    

    public abstract class BaseRepository<TIEntity>
    {
        protected PagedList<TIEntity> PagedList(
            ICriteria criteria,
            int pageIndex,
            int pageSize)
        {
            var countCriteria = CriteriaTransformer.Clone(criteria);
            var listCriteria = CriteriaTransformer.Clone(criteria);
            var results = new PagedList<TIEntity> { PageIndex = pageIndex, PageSize = pageSize };

            countCriteria.ClearOrders();
            countCriteria.SetProjection(Projections.RowCount());

            listCriteria.SetFirstResult((pageIndex - 1) * pageSize)
                .SetMaxResults(pageSize);

            results.TotalCount = countCriteria.UniqueResult<int>();
            results.AddRange(listCriteria.List<TIEntity>());

            return results;
        }

        protected PagedList<TIEntity> PagedList(
            ICriteria criteria,
            int pageIndex,
            int pageSize,
            Func<TIEntity, bool> searchCriteria,
            Func<TIEntity, object> orderBy,
            bool ascending)
        {
            var countCriteria = CriteriaTransformer.Clone(criteria);
            var listCriteria = CriteriaTransformer.Clone(criteria);
            var results = new PagedList<TIEntity> { PageIndex = pageIndex, PageSize = pageSize };

            countCriteria.ClearOrders();
            countCriteria.SetProjection(Projections.RowCount());

            listCriteria.SetFirstResult((pageIndex - 1) * pageSize)
                .SetMaxResults(pageSize);

            var tempList = listCriteria.List<TIEntity>();

            var filterList = tempList.Where(searchCriteria);

            results.TotalCount = filterList.Count();

            if (ascending)
            {
                results.AddRange(filterList.OrderBy(orderBy));
            }
            else 
            {
                results.AddRange(filterList.OrderByDescending(orderBy));
            }

            return results;
        }
    }
}